/*
 * Copyright (c) 2021 The excel-father Project
 *
 * Licensed under the Apache License, version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.inyourcode.excel.iml;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.base.Strings;
import com.google.common.io.Files;
import com.inyourcode.excel.ExportContext;
import com.inyourcode.excel.ExportException;
import com.inyourcode.excel.api.IExporter;
import com.inyourcode.excel.model.SheetDataModel;
import com.inyourcode.excel.model.column.CommentColData;
import com.inyourcode.excel.model.column.NameColData;
import com.inyourcode.excel.model.column.RowColData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * json数据导出
 * @author JackLei
 */
public class JsonExporter implements IExporter {
    static Logger LOGGER = LoggerFactory.getLogger(JsonExporter.class);
    /** 配置属性的key: json导出路径 */
    private static final String KEY_JSON_OUT_PATH = "json.out.path";
    private static final String KEY_JSON_DATA_TYPE = "json.out.data.type";

    @Override
    public boolean check(ExportContext context) throws ExportException {
        String outPath = context.getProperties().getProperty(KEY_JSON_OUT_PATH);
        if (Strings.isNullOrEmpty(outPath)) {
            throw new ExportException("Please set json export path");
        }
        return true;
    }

    @Override
    public void export(ExportContext context) throws ExportException {
        String outPath = context.getProperties().getProperty(KEY_JSON_OUT_PATH);
        String jsonDataType = context.getProperties().getProperty(KEY_JSON_DATA_TYPE);
        LOGGER.info("JSON_OUT_PATH={}", outPath);
        Map<String, JsonDataDTO> jsonMap = convertToJsonData(context.getSheetDataModelMap(), jsonDataType);
        doWriteToJsonFile(outPath, jsonMap);
    }

    /**
     * 生成json文件
     * @param outPath 导出绝对路径
     * @param jsonMap 导出的数据
     * @throws ExportException
     */
    private static void doWriteToJsonFile(String outPath, Map<String, JsonDataDTO> jsonMap) throws ExportException{
        for (Map.Entry<String, JsonDataDTO> entry : jsonMap.entrySet()) {
            String k = entry.getKey();
            JsonDataDTO v = entry.getValue();
            try {
                File file = new File(outPath + File.separator + k + ".json");
                if (!file.exists()) {
                    file.createNewFile();
                }
                Files.write(JSONObject.toJSONString(v.getSrcData(), SerializerFeature.PrettyFormat).getBytes(StandardCharsets.UTF_8), file);
                LOGGER.info("export json:{}", file.getName());
            } catch (IOException e) {
                String errStr = String.format("write to json file errpr, out path = %s", outPath);
                LOGGER.error("write to json file errpr, out path = {}", outPath);
                throw new ExportException(errStr, e);
            }
        }
    }

    /**
     * 将excel数据转成json数据
     * @param sheetDataModelMap
     * @return
     * @throws ExportException
     */
    private static Map<String, JsonDataDTO> convertToJsonData(Map<String, SheetDataModel> sheetDataModelMap, String jsonSrcType) throws ExportException {
        Map<String, JsonDataDTO> jsonMap = new HashMap<>();

        //遍历所有表格
        for (Map.Entry<String, SheetDataModel> entry : sheetDataModelMap.entrySet()) {
            String sheetName = entry.getKey();
            SheetDataModel sheetModel = entry.getValue();
            JsonDataDTO dto = new JsonDataDTO();
            dto.srcType = jsonSrcType;
            try {
                CommentColData[] commentHeader = sheetModel.getCommentHeader();
                NameColData[] nameHeader = sheetModel.getNameHeader();
                ArrayList<RowColData[]> rows = sheetModel.getRows();

                if (nameHeader == null) {
                    throw  new ExportException("please configure the property columns, sheet name = " + sheetName);
                }

                if (commentHeader == null) {
                    throw  new ExportException("please configure the data type columns, sheet name = " + sheetName);
                }

                //遍历表格的所有行，把每行数据存dto
                for (int index = 0; index < rows.size(); index++) {
                    RowColData[] colDataArray = rows.get(index);
                    //默认第一列为主键
                    Object primaryKey = null;
                    //遍历所有一行的所有列，把每列数据存在colMap
                    Map<Object, Object> colMap = new HashMap<>();
                    for (int col = 0; col < colDataArray.length; col++) {
                        try {
                            if (col == 0) {
                                primaryKey = colDataArray[col].getVal();
                            }

                            boolean ignore = commentHeader[col].isIgnore();
                            if (!ignore) {
                                colMap.put(nameHeader[col].getVal(), colDataArray[col].getVal());
                            }
                        } catch (Exception ex) {
                            String errStr = String.format("Error parsing row data ,sheet name = %s, row = %s, col = %s", sheetName, index, col);
                            LOGGER.error("Error parsing row data", ex);
                            throw new ExportException(errStr, ex);
                        }
                    }
                    if (jsonSrcType.equals("map")) {
                        dto.srcMapData.put(String.valueOf(primaryKey), colMap);
                    } else if (jsonSrcType.equals("list")) {
                        dto.srcListData.add(colMap);
                    }

                }

                jsonMap.put(sheetName, dto);
            } catch (Exception ex) {
                LOGGER.error("export json exception", ex);
                throw new ExportException("export json exception", ex);
            }
        }

        return jsonMap;
    }


    static class JsonDataDTO {
        String srcType = "";
        Map<String, Map> srcMapData = new HashMap<>();
        List<Map> srcListData = new ArrayList<>();

        Object getSrcData() {
            if (srcType.equals("list")) {
                return srcListData;
            }

            if (srcType.equals("map")) {
                return srcMapData;
            }

            return null;
        }
    }
}
